package org.kanstantin.nwscan.crawler;

import jcifs.smb.NtlmPasswordAuthentication;
import jcifs.smb.SmbException;
import jcifs.smb.SmbFile;
import org.kanstantin.nwscan.crawler.network.HostFinder;
import org.kanstantin.nwscan.crawler.network.NetworkScanner;

import java.io.*;
import java.net.InetAddress;
import java.net.MalformedURLException;
import java.net.UnknownHostException;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.logging.Logger;
import java.util.regex.Pattern;

/**
 * @author kanstantin
 */
public class SambaScannerImpl implements NetworkScanner {
    private List<String> hosts;
    private String subNetwork;

    private NtlmPasswordAuthentication NtlmAuth = null;
    private HostFinder hostFinder;

    private ThreadPoolExecutor threadPool = null;
    private final BlockingQueue<Runnable> queue = new ArrayBlockingQueue<Runnable>(1000);

    private final static Logger Log = Logger.getLogger(SambaScannerImpl.class.getName());
    private Map<String, Object> context = null;
    private File outputDir;
	private ResultsWritable resultsWriter = new LuceneIndexWriter(); //new FileResultProcessor();
	private ResultsContainer resultContainer = new ResultsContainerImpl();

    public SambaScannerImpl(Map<String, Object> ctx) {
        context = ctx;

        NtlmAuth = NtlmPasswordAuthentication.class.cast(context.get("NTLMAUTH"));
        hostFinder = HostFinder.class.cast(context.get("HOSTFINDER"));
        subNetwork = String.class.cast(context.get("SUBNET"));
        outputDir  = File.class.cast(context.get("OUTPUTDIR"));

	    resultsWriter.setOutputDir(outputDir);
	    resultContainer.setResultsWriter(resultsWriter);
    }

    public void setNtlmAuth(NtlmPasswordAuthentication ntlmAuth) {
        NtlmAuth = ntlmAuth;
    }

    public void setSubNetwork(String subNetwork) {
        this.subNetwork = subNetwork;
    }

    public void scanHosts() {

        hostFinder.scan();
        hosts = hostFinder.getHostList();

        threadPool = new ThreadPoolExecutor(40, 200, 500, TimeUnit.MILLISECONDS, queue);

        // Starting the monitor thread as a daemon
        Thread monitor = new Thread(new MyMonitorThread(threadPool));
        monitor.setDaemon(true);
        monitor.start();

        for (String h: hosts) {
	        SambaScannerWorker task = new SambaScannerWorker(h);
	        task.setNtlmAuth(NtlmAuth);
	        task.setResultContainer(resultContainer);

            while (queue.remainingCapacity() == 0) {
                try {
                    Thread.currentThread().sleep(500);
                } catch (InterruptedException ex) {
                    throw new RuntimeException(ex);
                }
            }
            threadPool.execute(task);
        }

        threadPool.shutdown();

        do {
            try {
                Thread.currentThread().sleep(1000);
            }
            catch (InterruptedException ex) {
                Log.severe("InterruptedException occured" + ex);
            }
        } while (threadPool.getActiveCount() > 0);

        resultsWriter.close();
    }


    public HostFinder getHostFinder() {
        return hostFinder;
    }

    public void setHostFinder(HostFinder hostFinder) {
        this.hostFinder = hostFinder;
    }

}
